package kr.momo.tmaker 
{
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	/**
	 * ...
	 * @author momo
	 */
	public class TransController extends Sprite
	{
		private var _targetObject:DesignItem;
		public function get targetObject():DesignItem { 
			return _targetObject;
		}
		public function set targetObject(value:DesignItem):void { 
			if ( _targetObject != null ) {
				if ( _targetObject == value ) return;
				_targetObject.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler );
			}
			_targetObject = value;
			_targetObject.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler );
			
			controllerAlign();
		}
		
		private var controllerTL:MovieClip;
		private var controllerTC:MovieClip;
		private var controllerTR:MovieClip;
		private var controllerCL:MovieClip;
		private var controllerCC:MovieClip;
		private var controllerCR:MovieClip;
		private var controllerBL:MovieClip;
		private var controllerBC:MovieClip;
		private var controllerBR:MovieClip;
		private var controllerRotate:MovieClip;
		
		private var mouseDownPoint:Point;
		private var targetTransStartPoint:Point;
		private var targetTransStartWidth:Number;
		private var targetTransStartHeight:Number;
		private var targetTransStartCenterPoint:Point;
		
		private var currentControllerTarget:*;
		
		private var zoom:Number = 1;
		
		
		public function TransController() 
		{
			controllerTL = new MC_TransControllerGuide();
			controllerTC = new MC_TransControllerGuide();
			controllerTR = new MC_TransControllerGuide();
			controllerCL = new MC_TransControllerGuide();
			controllerCC = new MC_TransControllerGuide();
			controllerCR = new MC_TransControllerGuide();
			controllerBL = new MC_TransControllerGuide();
			controllerBC = new MC_TransControllerGuide();
			controllerBR = new MC_TransControllerGuide();
			controllerRotate = new MC_RotateControllerGuide();
			
			addChild( controllerTL );
			addChild( controllerTC );
			addChild( controllerTR );
			addChild( controllerCL );
			addChild( controllerCC );
			addChild( controllerCR );
			addChild( controllerBL );
			addChild( controllerBC );
			addChild( controllerBR );
			addChild( controllerRotate );
			
			controllerTL.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler );
			controllerTC.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler );
			controllerTR.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler );
			controllerCL.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler );
			controllerCC.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler );
			controllerCR.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler );
			controllerBL.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler );
			controllerBC.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler );
			controllerBR.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler );
			controllerRotate.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler );
			
			addEventListener(Event.ENTER_FRAME, enterFrameHandler );
		}
		
		private function enterFrameHandler(e:Event):void 
		{
			if ( visible && _targetObject ) controllerAlign();
			
			
		}
		
		private function mouseUpHandler(e:MouseEvent):void 
		{
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveEvent );
			stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler );
			
			currentControllerTarget = null;
		}
		
		private function mouseDownHandler(e:MouseEvent):void 
		{
			mouseDownPoint = new Point( e.stageX, e.stageY );
			targetTransStartPoint = new Point( _targetObject.x, _targetObject.y );
			currentControllerTarget = e.currentTarget;
			
			targetTransStartWidth = _targetObject.originWidth * _targetObject.itemScaleX;
			targetTransStartHeight = _targetObject.originHeight * _targetObject.itemScaleY;
			
			switch( currentControllerTarget ) {
				case _targetObject:
					
					
				break;
				
				case controllerTL:
					
				break;
				case controllerTC:
					
				break;
				case controllerTR:
					
				break;
				case controllerCL:
					
				break;
				case controllerCC:
					
				break;
				case controllerCR:
					
				break;
				case controllerBL:
					
				break;
				case controllerBC:
					
				break;
				case controllerBR:
					
				break;
				case controllerRotate:
					//targetTransStartRotation = _targetObject.rotation;
					var targetObjectWidth:Number = _targetObject.originWidth * _targetObject.itemScaleX;
					var targetObjectHeight:Number = _targetObject.originHeight * _targetObject.itemScaleY;
					targetTransStartCenterPoint = globalToLocal( _targetObject.localToGlobal( new Point( targetObjectWidth * 0.5, targetObjectHeight * 0.5 ) ));
					//targetTransStartTLPoint = globalToLocal( _targetObject.localToGlobal( new Point() ));
				break;
			}
			
			stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveEvent );
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler );
		}
		
		private function mouseMoveEvent(e:MouseEvent):void 
		{
			var nowPoint:Point;
			var movePoint:Point;
			var rotateMovePoint:Point;
			
			nowPoint = new Point( e.stageX, e.stageY );
			movePoint = nowPoint.subtract( mouseDownPoint );
			
			// 1. movePoint 의 angle과 length를 구한다.
			// 2. 적용하려는 targetObject 의 각도에 movePoint의 각도를 빼서 실제 적용 각도를 구한다.
			// 3. 해당 각도로 length 만큼 이동시켜 계산한다.
			var targetRadian:Number = _targetObject.rotation * Math.PI / 180;
			var moveRadian:Number = Math.atan2( movePoint.y, movePoint.x );
			var realRadian:Number = targetRadian - moveRadian;
			var length:Number = movePoint.length;
			
			// 4. 타겟의 원래 크기 값과 스케일 값에 비례하려 계산
			//_targetObject.originWidth : 1 = targetTransStartWidth + movePoint.x : x
			
			switch( currentControllerTarget ) {
				case _targetObject:
					// 단순 이동
					var deltaPoint:Point = new Point( targetTransStartPoint.x + movePoint.x, targetTransStartPoint.y + movePoint.y );
					_targetObject.x = deltaPoint.x;
					_targetObject.y = deltaPoint.y;
				break;
				case controllerTL:
					movePoint.x = -(Math.cos( realRadian ) * length);
					movePoint.y = (Math.sin( realRadian ) * length);
					
					_targetObject.setScaleX( (targetTransStartWidth + movePoint.x) / _targetObject.originWidth );
					_targetObject.setScaleY( (targetTransStartHeight + movePoint.y) / _targetObject.originHeight );
					
					// Y축 처리
					rotateMovePoint = new Point( (Math.sin( targetRadian ) * movePoint.y), -(Math.cos( targetRadian ) * movePoint.y) );
					_targetObject.x = targetTransStartPoint.x + rotateMovePoint.x;
					_targetObject.y = targetTransStartPoint.y + rotateMovePoint.y;
					
					// X축 처리
					rotateMovePoint = new Point( (Math.cos( targetRadian ) * movePoint.x), (Math.sin( targetRadian ) * movePoint.x) );
					_targetObject.x -= rotateMovePoint.x;
					_targetObject.y -= rotateMovePoint.y;
				break;
				case controllerTC:
					movePoint.y = (Math.sin( realRadian ) * length);
					_targetObject.setScaleY( (targetTransStartHeight + movePoint.y) / _targetObject.originHeight );
					
					rotateMovePoint = new Point( (Math.sin( targetRadian ) * movePoint.y), -(Math.cos( targetRadian ) * movePoint.y) );
					_targetObject.x = targetTransStartPoint.x + rotateMovePoint.x;
					_targetObject.y = targetTransStartPoint.y + rotateMovePoint.y;
				break;
				case controllerTR:
					movePoint.x = (Math.cos( realRadian ) * length);
					movePoint.y = (Math.sin( realRadian ) * length);
					
					_targetObject.setScaleX( (targetTransStartWidth + movePoint.x) / _targetObject.originWidth );
					_targetObject.setScaleY( (targetTransStartHeight + movePoint.y) / _targetObject.originHeight );
					
					rotateMovePoint = new Point( (Math.sin( targetRadian ) * movePoint.y), -(Math.cos( targetRadian ) * movePoint.y) );
					_targetObject.x = targetTransStartPoint.x + rotateMovePoint.x;
					_targetObject.y = targetTransStartPoint.y + rotateMovePoint.y;
				break;
				case controllerCL:
					movePoint.x = -(Math.cos( realRadian ) * length);
					_targetObject.setScaleX( (targetTransStartWidth + movePoint.x) / _targetObject.originWidth );
					
					rotateMovePoint = new Point( (Math.cos( targetRadian ) * movePoint.x), (Math.sin( targetRadian ) * movePoint.x) );
					_targetObject.x = targetTransStartPoint.x - rotateMovePoint.x;
					_targetObject.y = targetTransStartPoint.y - rotateMovePoint.y;
				break;
				case controllerCC:
					
				break;
				case controllerCR:
					movePoint.x = Math.cos( realRadian ) * length;
					_targetObject.setScaleX( (targetTransStartWidth + movePoint.x) / _targetObject.originWidth );
				break;
				case controllerBL:
					movePoint.x = -(Math.cos( realRadian ) * length);
					movePoint.y = -(Math.sin( realRadian ) * length);
					
					_targetObject.setScaleX( (targetTransStartWidth + movePoint.x) / _targetObject.originWidth );
					_targetObject.setScaleY( (targetTransStartHeight + movePoint.y) / _targetObject.originHeight );
					
					// x축 이동만큼 이동해야함
					//_targetObject.x movePoint.x
					// rotateMovePoint.x 가 이동 길이이다. 이를 각도로 x,y 를 다시 구해야 한다.
					//trace( realRadian );
					rotateMovePoint = new Point( (Math.cos( targetRadian ) * movePoint.x), (Math.sin( targetRadian ) * movePoint.x) );
					_targetObject.x = targetTransStartPoint.x - rotateMovePoint.x;
					_targetObject.y = targetTransStartPoint.y - rotateMovePoint.y;
				break;
				case controllerBC:
					movePoint.y = -(Math.sin( realRadian ) * length);	// y축 뒤집히기 때문에
					_targetObject.setScaleY( (targetTransStartHeight + movePoint.y) / _targetObject.originHeight );
				break;
				case controllerBR:
					movePoint.x = Math.cos( realRadian ) * length;
					movePoint.y = -(Math.sin( realRadian ) * length);	// y축 뒤집히기 때문에
					
					_targetObject.setScaleX( (targetTransStartWidth + movePoint.x) / _targetObject.originWidth );
					_targetObject.setScaleY( (targetTransStartHeight + movePoint.y) / _targetObject.originHeight );
				break;
				
				case controllerRotate:
					// 1.오브젝트를 중심점으로 이동
					// 2.오브젝트 중심점을 기준으로 rotation 을 구함
					movePoint = nowPoint.subtract( targetTransStartCenterPoint );
					
					// 마우스 클릭지점을 중심으로가 아니고 오브젝트의 원점을 중심으로 라디안을 구하기 때문에 (90 * 180 / Math.PI) 를 더해서 보정한다.
					moveRadian = Math.atan2( movePoint.y, movePoint.x ) + (90 * Math.PI / 180);
					_targetObject.rotation = moveRadian * 180 / Math.PI;
					
					// 중심점을 기준으로 돌았을때 수정 x,y 값 적용
					// ----------------  원래 _targetObject 의 0,0 과의 각도 ( 이건 scale 조절시에만 변경된다. ) -------------//
					var tempPointX:Number;
					var tempPointY:Number;
					if ( _targetObject.itemScaleX < 0 ) {
						tempPointX = (_targetObject.itemWidth * 0.5);
					} else {
						tempPointX = -(_targetObject.itemWidth * 0.5);
					}
					if ( _targetObject.itemScaleY < 0 ) {
						tempPointY = (_targetObject.itemHeight * 0.5);
					} else {
						tempPointY = -(_targetObject.itemHeight * 0.5);
					}
					
					//var centerToTLPoint:Point = new Point( -(_targetObject.itemWidth * 0.5), -(_targetObject.itemHeight * 0.5) );
					var centerToTLPoint:Point = new Point( tempPointX, tempPointY );
					var centerToTLLength:Number = centerToTLPoint.length;
					var centerToTLRadian:Number = Math.atan2( centerToTLPoint.y, centerToTLPoint.x );
					// centerToTLPoint 도 로테이트 되어있는 만큼 적용해서 구하기
					
					// centerToTLRadian 과 moveRadian 만큼 이동한 후의 
					rotateMovePoint = new Point( (Math.cos( centerToTLRadian + moveRadian ) * centerToTLLength), (Math.sin( centerToTLRadian + moveRadian ) * centerToTLLength) );
					var centerDeltaPoint:Point = rotateMovePoint.subtract(centerToTLPoint);// .subtract( rotateMovePoint );
					_targetObject.x = targetTransStartCenterPoint.x + centerDeltaPoint.x + tempPointX;
					_targetObject.y = targetTransStartCenterPoint.y + centerDeltaPoint.y + tempPointY;
					
					/*
					// 특정 좌표를 중심으로 회전이동한 좌표 구하는 공식
					//var rx:Number = (px - cx) * Math.cos(R) - (py - cy) * Math.sin(R);
                    //var ry:Number = (px - cx) * Math.sin(R) + (py - cy) * Math.cos(R);
					var rx:Number = (targetTransStartPoint.x - targetTransStartCenterPoint.x) * Math.cos(moveRadian) - (targetTransStartPoint.y - targetTransStartCenterPoint.y) * Math.sin(moveRadian);
                    var ry:Number = (targetTransStartPoint.x - targetTransStartCenterPoint.x) * Math.sin(moveRadian) + (targetTransStartPoint.y - targetTransStartCenterPoint.y) * Math.cos(moveRadian);
					_targetObject.x = targetTransStartCenterPoint.x + rx;
					_targetObject.y = targetTransStartCenterPoint.y + ry;
					*/
				break;
			}
		}
		
		private function controllerAlign():void 
		{
			// TODO: itemWidth, itemHeight 의 -(음수)가 안되는 문제 해결하기 위해 스케일값으로 계산
			var targetObjectWidth:Number = _targetObject.originWidth * _targetObject.itemScaleX;
			var targetObjectHeight:Number = _targetObject.originHeight * _targetObject.itemScaleY;
			
			var tl:Point = globalToLocal( _targetObject.localToGlobal( new Point() ));
			var tc:Point = globalToLocal( _targetObject.localToGlobal( new Point( targetObjectWidth * 0.5, 0) ));
			var tr:Point = globalToLocal( _targetObject.localToGlobal( new Point( targetObjectWidth, 0) ));
			var cl:Point = globalToLocal( _targetObject.localToGlobal( new Point( 0, targetObjectHeight * 0.5) ));
			var cc:Point = globalToLocal( _targetObject.localToGlobal( new Point( targetObjectWidth * 0.5, targetObjectHeight * 0.5 ) ));
			var cr:Point = globalToLocal( _targetObject.localToGlobal( new Point( targetObjectWidth, targetObjectHeight * 0.5 ) ));
			var bl:Point = globalToLocal( _targetObject.localToGlobal( new Point( 0, targetObjectHeight ) ));
			var bc:Point = globalToLocal( _targetObject.localToGlobal( new Point( targetObjectWidth * 0.5, targetObjectHeight ) ));
			var br:Point = globalToLocal( _targetObject.localToGlobal( new Point( targetObjectWidth, targetObjectHeight ) ));
			
			controllerTL.x = tl.x;
			controllerTL.y = tl.y;
			controllerTC.x = tc.x;
			controllerTC.y = tc.y;
			controllerTR.x = tr.x;
			controllerTR.y = tr.y;
			controllerCL.x = cl.x;
			controllerCL.y = cl.y;
			controllerCC.x = cc.x;
			controllerCC.y = cc.y;
			controllerCR.x = cr.x;
			controllerCR.y = cr.y;
			controllerBL.x = bl.x;
			controllerBL.y = bl.y;
			controllerBC.x = bc.x;
			controllerBC.y = bc.y;
			controllerBR.x = br.x;
			controllerBR.y = br.y;
			
			// TODO: 스케일 Y가 - 값이 되어도 정상작동 하도록 수정
			controllerRotate.x = tc.x;
			controllerRotate.y = tc.y;
			controllerRotate.rotation = _targetObject.rotation;
		}
		
		public function mouseDown():void {
			if ( _targetObject == null ) return;
			
			mouseDownPoint = new Point( stage.mouseX, stage.mouseY );
			currentControllerTarget = _targetObject;
			
			targetTransStartPoint = new Point( _targetObject.x, _targetObject.y );
			//targetTransStartWidth = _targetObject.itemWidth;
			//targetTransStartHeight = _targetObject.itemHeight;
			targetTransStartWidth = _targetObject.originWidth * _targetObject.itemScaleX;
			targetTransStartHeight = _targetObject.originHeight * _targetObject.itemScaleY;
			
			stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveEvent );
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler );
		}
		
	}

}